#ifndef SH_BYTEARRAY_H
#define SH_BYTEARRAY_H

#include <string>

namespace sh
{
/**
 * an array of bytes
 *
 * @author: sherlock_lht
 */
class ByteArray
{
public:
    static char toHexLower(uint32_t value) noexcept;
    static char toHexUpper(uint32_t value) noexcept;
    static int32_t fromHex(uint32_t c) noexcept;
    static ByteArray fromHex(const std::string &str) noexcept;

public:
    explicit ByteArray();
    explicit ByteArray(const char *data, int32_t size = -1);
    explicit ByteArray(const std::string &data);
    explicit ByteArray(int32_t size, char ch);
    ByteArray(const ByteArray &other);
    virtual ~ByteArray();

    ByteArray &append(const ByteArray &ba);
    ByteArray &append(const std::string &str);
    ByteArray &append(const char *str);
    ByteArray &append(const char *str, int32_t len);
    ByteArray &append(char ch);

    char at(int32_t index) const;
    int32_t capacity() const;
    void chop(int32_t n);
    void clear();
    bool contain(const ByteArray &ba) const;
    bool contain(const char *str) const;
    bool contain(char ch) const;
    int32_t count() const;
    std::string data() const;
    std::string &data();
    bool endsWith(const ByteArray &ba) const;
    bool endsWith(const char *str) const;
    bool endsWith(char ch) const;
    ByteArray &fill(char ch, int32_t size = -1);
    int32_t indexOf(const ByteArray &ba, int32_t from = 0) const;
    int32_t indexOf(const std::string &str, int32_t from = 0) const;
    int32_t indexOf(const char *str, int32_t from = 0) const;
    int32_t indexOf(char ch, int32_t from = 0) const;
    ByteArray &insert(int32_t i, const ByteArray &ba);
    ByteArray &insert(int32_t i, const std::string &str);
    ByteArray &insert(int32_t i, const char *str);
    ByteArray &insert(int32_t i, const char *str, int32_t len);
    ByteArray &insert(int32_t i, char ch, int32_t len = 0);
    bool isEmpty() const;
    int32_t lastIndexOf(const ByteArray &ba, int32_t from = -1) const;
    int32_t lastIndexOf(const std::string &str, int32_t from = -1) const;
    int32_t lastIndexOf(const char *str, int32_t from = -1) const;
    int32_t lastIndexOf(char ch, int32_t from = -1) const;
    ByteArray left(int32_t len) const;
    ByteArray leftJustified(int32_t width, char fill = ' ', bool truncate = false) const;
    int32_t length() const;
    ByteArray mid(int32_t pos, int32_t len = -1) const;
    ByteArray &prepend(const ByteArray &ba);
    ByteArray &prepend(const char *str);
    ByteArray &prepend(const char *str, int32_t len);
    ByteArray &prepend(char ch, int32_t len = 0);
    void push_back(const ByteArray &other);
    void push_back(const char *str);
    void push_back(char ch);
    void push_front(const ByteArray &other);
    void push_front(const char *str);
    void push_front(char ch, int32_t len = 0);
    ByteArray &remove(int32_t pos, int32_t len);
    ByteArray repeated(int32_t times) const;
    ByteArray &replace(int32_t pos, int32_t len, const ByteArray &after);
    ByteArray &replace(int32_t pos, int32_t len, const char *after);
    ByteArray &replace(int32_t pos, int32_t len, const char *after, int32_t alen);
    ByteArray &replace(const ByteArray &before, const ByteArray &after);
    ByteArray &replace(const std::string &before, const std::string &after);
    void reserve(int32_t size);
    void resize(int32_t size);
    ByteArray right(int32_t len) const;
    ByteArray rightJustified(int32_t width, char fill = ' ', bool truncate = false) const;
    int32_t size() const;
    bool startsWith(const ByteArray &ba) const;
    bool startsWith(const char *str) const;
    bool startsWith(char ch) const;
    void swap(ByteArray &other);
    ByteArray toHex() const;
    bool operator!=(const std::string &str) const;
    ByteArray &operator+=(const ByteArray &ba);
    ByteArray &operator+=(const std::string &str);
    ByteArray &operator+=(const char *str);
    ByteArray &operator+=(char ch);
    bool operator<(const std::string &str) const;
    bool operator<=(const std::string &str) const;
    ByteArray &operator=(const ByteArray &other);
    ByteArray &operator=(const char *str);
    bool operator==(const std::string &str) const;
    bool operator>(const std::string &str) const;
    bool operator>=(const std::string &str) const;
    char operator[](int32_t i) const;
    char operator[](uint32_t i) const;

protected:
    std::string originData;
};
}

#endif//SH_BYTEARRAY_H
